/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "File.h"
#include "FileSystem.h"
#include <stdio.h>

namespace liba
{

namespace filesystem
{

struct File::Impl
{
	FILE * handle;
};



File::File(const filesystem::String & name, Mode mode)
	:	impl(new Impl())
{
	if(mode == WRITE)
	{
		filesystem::create_directory_tree(name);
	}

	const char * access = mode == READ ? "rb" : mode == WRITE ? "wb" : "ab";
	FILE * file = fopen( name.c_str(), access );
	impl->handle = file;
	}

bool File::is_valid()const
{
	return impl->handle != 0;
}

File::~File()
{
	if( impl->handle != 0 )
		fclose( impl->handle );
	delete impl; impl = 0;
}

size_t File::write(const void * data, size_t count)
{
	if(!is_valid())
		return 0;

	unsigned bytes_written = fwrite( data, 1, count, impl->handle );
	return bytes_written;
}

size_t File::read(void * data, size_t count)
{
	if(!is_valid())
		return 0;

	unsigned bytes_read = fread( data, 1, count, impl->handle );
	return bytes_read;
}

size_t File::skip(size_t count)
{
	if(!is_valid())
		return 0;

	unsigned old_position = ftell( impl->handle );
	fseek( impl->handle, count, SEEK_CUR );
	unsigned new_position = ftell( impl->handle );
	return new_position - old_position;
}

size_t File::get_size()const
{
	if(!is_valid())
		return 0;

	unsigned curr_pos = ftell( impl->handle );
	fseek( impl->handle, 0, SEEK_END );
	unsigned size = ftell( impl->handle );
	fseek( impl->handle, curr_pos, SEEK_SET );
	return size;
}

size_t File::get_position()const
{
	if(!is_valid())
		return 0;

	unsigned pos = ftell( impl->handle );
	return pos;
}

void File::reset(size_t position)
{
	if(!is_valid())
		return;

	fseek( impl->handle, position, SEEK_SET );
}

void File::flush()
{
	if(!is_valid())
		return;

	fflush( impl->handle );
}

}//namespace filesystem

}//namespace liba

